﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.IO;
using System.Windows.Forms;

using NetworkServices;
using SearchRS;

namespace RapidSearcher
{
    public static class Program
    {
        private static SearchResults m_searchResults;

        private static string m_searchOrder;
        public static ManualResetEvent m_shouldStopEvent = new ManualResetEvent(false);
        private static string m_rsCreds;
        private static DMLinks m_dmLinks;
        private static string m_destRoot;
        private static string m_dlPath;
        private static bool searchAppsAndGamesAndEbooksToo;
        private static bool searchSubsSite;
        private static SearchRS.SearchRS m_searchRs;
        private static OperationMode m_operationMode;
        private static WarezBBSearcher warezBBSearcher;
        //private static ProjectWSearcher projectwSearcher;
        private static INotifications guiNotifier;
        private static RapidSearcher m_rapidSearcher;
        
        public static void InitFromConfiguration()
        {
            m_searchOrder = Properties.Settings.Default.SearchOrder;
            m_rsCreds = Properties.Settings.Default.RsCreds;

            string DMPath = Properties.Settings.Default.FDMPath;
            if (!String.IsNullOrEmpty(DMPath))
            {
                m_dmLinks = new FDMLinks(DMPath + "\\fdm.exe");
            }
            else
            {
                DMPath = Properties.Settings.Default.IDMPath;
                if (!string.IsNullOrEmpty(DMPath))
                {
                    m_dmLinks = new IDMLinks(DMPath + "\\IDMan.exe");
                }
                else
                {
                    DMPath = Properties.Settings.Default.JDPath;
                    if (!string.IsNullOrEmpty(DMPath))
                    {
                        m_dmLinks = new JDLinks(DMPath + "\\JDownloader.exe");
                    }
                }
            }

            m_destRoot = Properties.Settings.Default.DestRoot;
            m_dlPath = Properties.Settings.Default.DlPath;

            var searchRsParams = new SearchRsParams()
            {
                OperationMode = m_operationMode,
                SearchResults = m_searchResults,
                RsCreds = m_rsCreds,
                DmLinks = m_dmLinks,
                DestRoot = m_destRoot,
                DlPath = m_dlPath,
                ShouldStopEvent = m_shouldStopEvent
            };

            switch (m_operationMode)
            {
                case OperationMode.CLI:
                    {
                        if (m_searchResults == null)
                            m_searchResults = new SearchResults(null, m_operationMode);

                        searchRsParams.SearchResults = m_searchResults;

                        if (warezBBSearcher == null)
                        {
                            ConsoleNotifier consoleNotifier = new ConsoleNotifier();
                            warezBBSearcher = new WarezBBSearcher(consoleNotifier, searchRsParams);
                            //projectwSearcher = new ProjectWSearcher(consoleNotifier, searchRsParams);
                        }
                        else
                        {
                            warezBBSearcher.SetSearchParams(searchRsParams);
                            //projectwSearcher.SetSearchParams(searchRsParams);                            
                        }
                        
                        m_searchRs = new SearchRS.SearchRS(searchRsParams);
                        break;
                    }

                case OperationMode.GUI:
                    {
                        if (m_rapidSearcher == null)
                        {
                            m_rapidSearcher = new RapidSearcher();
                        }
                        if (m_searchResults == null)
                            m_searchResults = new SearchResults(m_rapidSearcher, m_operationMode);
                        searchRsParams.SearchResults = m_searchResults;

                        if (warezBBSearcher == null)
                        {
                            guiNotifier = new GuiNotifier(m_rapidSearcher);
                            warezBBSearcher = new WarezBBSearcher(guiNotifier, searchRsParams);
                            //projectwSearcher = new ProjectWSearcher(guiNotifier, searchRsParams);
                        }
                        else
                        {
                            warezBBSearcher.SetSearchParams(searchRsParams);
                            //projectwSearcher.SetSearchParams(searchRsParams);
                        }

                        m_searchRs = new SearchRS.SearchRS(searchRsParams);
                        break;
                    }

                case OperationMode.JDownloadePlugin:
                    {
                        if (m_searchResults == null)
                            m_searchResults = new SearchResults(null, m_operationMode);
                        searchRsParams.SearchResults = m_searchResults;

                        if (warezBBSearcher == null)
                        {
                            NullNotifier nullNotifier = new NullNotifier();
                            warezBBSearcher = new WarezBBSearcher(nullNotifier, searchRsParams);
                            //projectwSearcher = new ProjectWSearcher(nullNotifier, searchRsParams);
                        }
                        else
                        {
                            warezBBSearcher.SetSearchParams(searchRsParams);
                            //projectwSearcher.SetSearchParams(searchRsParams);                            
                        }

                        m_searchRs = new SearchRS.SearchRS(searchRsParams);
                        break;
                    }

                default:
                    throw new ArgumentException("invalid operation mode " + m_operationMode);

            }

        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThreadAttribute]
        static void Main(string []args)
        {
            if (args.Length > 0)
            {
                m_operationMode = (args.Length > 3 ? OperationMode.JDownloadePlugin : OperationMode.CLI);
            }
            else
            {
                m_operationMode = OperationMode.GUI;
            }

            InitFromConfiguration();

            switch (m_operationMode)
            {
                case OperationMode.CLI:
                    {
                        searchAppsAndGamesAndEbooksToo = args[1].Equals("true", StringComparison.OrdinalIgnoreCase);
                        if (args.Length > 2)
                            m_searchOrder = args[2];
                        Search(null, args[0].Replace("\"", " "));
                        Console.WriteLine("did not find any links.");
                        Environment.Exit(1);
                        break;
                    }
                case OperationMode.GUI:
                    {
                        if ( string.IsNullOrEmpty(m_searchOrder) || string.IsNullOrEmpty(m_dlPath) )
                        {
                            m_rapidSearcher.ShowConfigurationScreen();
                        }

                        m_rapidSearcher.ShowDialog();
                        break;
                    }
                case OperationMode.JDownloadePlugin:
                    {
                        searchAppsAndGamesAndEbooksToo = args[1].Equals("true", StringComparison.OrdinalIgnoreCase);
                        m_searchOrder = args[2];
                        Search(null, args[0].Replace("\"", " "));
                        break;
                    }
                default:
                    throw new ArgumentException("invalid operation mode " + m_operationMode);
            }
        }
        
        public static void DoSearchAndAdd(object obj)
        {
            RapidSearcher rapidSearcherForm = (RapidSearcher) obj;

            m_searchResults.Clear();
            m_shouldStopEvent.Reset();

            string searchString = rapidSearcherForm.GetSearchString();
            searchAppsAndGamesAndEbooksToo = rapidSearcherForm.SearchAppsAndGamesAndEbooksToo();
            searchSubsSite = rapidSearcherForm.SearchSubsSite();

            Search(rapidSearcherForm, searchString);

            SetStatusMessageAndProgressAmount(rapidSearcherForm, "Finished", 100);
            if (m_operationMode == OperationMode.GUI)
            {
                rapidSearcherForm.SetMode(false);
                rapidSearcherForm.SetSearchEnabled(true);
            }
        }

        public static void SetStop()
        {
            m_shouldStopEvent.Set();
            warezBBSearcher.SetStop();
            //projectwSearcher.SetStop();
        }


        private static void Search(RapidSearcher rapidSearcherForm, string searchString)
        {
            if (searchSubsSite)
            {
                int tries = 3;
                while (tries > 0)
                {
                    try
                    {
                        WebRequest req = NetworkServices.NetworkServices.SendPostRequest("http://www.torec.net/ssearch.asp", "", "", "search=" + searchString.Replace(" ", "+"), "");
                        WebResponse resp = req.GetResponse();
                        StreamReader sr = new StreamReader(resp.GetResponseStream());
                        String s = sr.ReadToEnd();

                        Regex re = new Regex("sub.asp\\?sub_id=[0-9]+");
                        Match m = re.Match(s);
                        if (m.Success)
                        {
                            searchString = "http://www.torec.net/" + m.Groups[0].Value;
                        }
                        break;
                    }
                    catch (Exception)
                    {
                        tries--;
                    }
                }
            }

            if (searchString.ToLower().Contains("sratim.co.il"))
            {
                SratimSearcher sratimSearcher = new SratimSearcher(m_searchOrder);
                TorecResults results = sratimSearcher.Search(searchString);
                foreach (TorecResult result in results.Results)
                {
                    SearchRsSites(rapidSearcherForm, result.Title, result.SubsLink);

                    if (ShouldStop())
                        break;
                }
            }
            else if (searchString.ToLower().StartsWith("http://www.torec", StringComparison.InvariantCultureIgnoreCase))
            {
                TorecSearcher torecSearcher = new TorecSearcher(m_searchOrder);
                TorecResults results = torecSearcher.Search(searchString);
                foreach (TorecResult result in results.Results)
                {
                    SearchRsSites(rapidSearcherForm, result.Title, result.SubsLink);

                    if (ShouldStop())
                        break;
                }
            }
/*            else if (searchString.ToLower().StartsWith("http://www.serethd",StringComparison.InvariantCultureIgnoreCase))
            {
                CollectSeretHDLinks(searchString, searchString);
                while (AsyncWebRequest.PendingRequests > 0)
                    Thread.Sleep(1000);
            }*/
            else
            {
                SearchRsSites(rapidSearcherForm, searchString, "");
            }
        }

        private static bool ShouldStop()
        {
            return m_shouldStopEvent.WaitOne(1, false);
        }

        private static void SearchRsSites(RapidSearcher rapidSearcherForm, string searchString, string subsLink)
        {
            searchString = Utils.Utils.CleanName(searchString);
            searchString = Utils.Utils.RemoveReleaseName(searchString);

            do
            {
                /*
                if (!searchAppsAndGamesAndEbooksToo && 
                    (m_searchOrder.Contains("720") || m_searchOrder.Contains("1080")) )
                {
                    SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching SeretHD", 10);
                    SearchSeretHD(searchString);
                }

                if (ShouldStop())
                    break;
                */

               /*
                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching BayW", 40);
                SearchPhpBBSite(rapidSearcherForm, "http://bayw.org", searchString, bayWSid);

                if (ShouldStop())
                    return;
                
                */

                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching IRFree", 10);
                SearchIRFree(searchString, subsLink);

                if (ShouldStop())
                    break;
                

                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching OneDDL", 20);
                SearchOneDDL(searchString, subsLink);


                if (ShouldStop())
                    break;

                /*
                SetStatusMessageAndProgressAmount(rapidSearcherForm ,"Searching GoLeech", 80);
                SearchGoLeech(searchString, subsLink);

                if (ShouldStop())
                    break;

                
                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching LinksLoads", 75);
                SearchLinksLoad(searchString, subsLink);

                if (ShouldStop())
                    break;
                */

                IdownSearcher idownSearcher = new IdownSearcher(m_searchRs, m_shouldStopEvent);
                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching Idown", 20);
                idownSearcher.Search(searchString);

                if (ShouldStop())
                    break;


/*                HoradotSearcher horadotSearcher = new HoradotSearcher(m_searchRs, m_shouldStopEvent);
                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching Horadot", 30);
                horadotSearcher.Search(searchString);

                if (ShouldStop())
                    break;

                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching ProjectW", 40);
                projectwSearcher.Search(searchString, searchAppsAndGamesAndEbooksToo, m_searchOrder, subsLink, false);
                
                if (ShouldStop())
                    break;*/

                SetStatusMessageAndProgressAmount(rapidSearcherForm, "Searching warez-bb", 60);
                warezBBSearcher.Search(searchString, searchAppsAndGamesAndEbooksToo, m_searchOrder, subsLink, false);

                if (ShouldStop())
                    break;
                
                while (AsyncWebRequest.PendingRequests > 0)
                    Thread.Sleep(1000);

            } while (false);
        }

        private static void SearchSeretHD(string searchString)
        {
            // Search
            string searchLink = "http://www.serethd.com/?s=" + searchString.Trim().Replace(" ", "+");

            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(searchLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                     SearchSeretHDCB, searchString);
        }

        private static void SearchSeretHDCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            if (buffer == null || buffer.Contains("לא מצאתי את מה שחיפשת") || buffer.Contains("לא נמצאו רשומות שתאמו את חיפושך"))
            {
                return;
            }

            string searchString = (string) userState;

            // Search result link
            string link = "";
            Regex pattern = new Regex("<h3 id=\"post-.+\"><a href=\"(.+)\" rel=\"bookmark\"");
            Match match = pattern.Match(buffer);
            if (match.Success)
            {
                link = match.Groups[1].Value;
                CollectSeretHDLinks(link, searchString);
            }
        }

        private static void CollectSeretHDLinks(string seretHDLink, string searchString)
        {
            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(seretHDLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                     CollectSeretHdLinksCB, new string[]{seretHDLink, searchString});
        }

        private static void CollectSeretHdLinksCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            int startPos;
            int endPos;

            string seretHDLink = ((string[])userState)[0];
            string searchString = ((string[])userState)[1];

            if (buffer == null)
                return;

            if (!Utils.Utils.AllWordsIncluded(buffer, searchString))
                return;

            // Submit links
            startPos = buffer.IndexOf("<div id=\"content\">");
            if (startPos == -1)
                return;
            startPos = buffer.IndexOf("http://www.filesonic.com/", startPos);
            if (startPos == -1)
                return;

            endPos = buffer.IndexOf("<p>", startPos);
            if (endPos == -1)
                return;

            string linksBuffer = buffer.Substring(startPos, endPos - startPos);

            string[] rsLinks = linksBuffer.Split(new[] { "http://www.filesonic.com/" },
                                                 StringSplitOptions.RemoveEmptyEntries);

            List<string> links = m_searchRs.CleanLinks(rsLinks);
            if (links == null || links.Count == 0)
                return;


            // Search for subtitles
            //

            string subsLink = "";
            if (links[links.Count-1].EndsWith(".srt"))
            {
                subsLink = links[links.Count - 1];
                links.RemoveAt(links.Count-1);
            }
            else
            {
                startPos = buffer.IndexOf("http://www.filesonic.com/", endPos);
                if (startPos > -1)
                {
                    endPos = buffer.IndexOf("&nbsp;", startPos);
                    if (endPos == -1)
                        endPos = buffer.IndexOf("</p>", startPos);
                    subsLink = buffer.Substring(startPos, endPos - startPos);
                    List<string> subsLinks = m_searchRs.CleanLinks(new string[] { subsLink });
                    links.Add(subsLinks[0]);
                }                
            }

            // Find Title
            //

            // title="Permanent Link to Dragon Naturally Speaking Preferred v10">Dragon Naturally Speaking Preferred v10</a>
            startPos = buffer.IndexOf("div class=\"post\"");
            startPos = buffer.IndexOf("<h2>", startPos);
            string title = "";
            if (startPos > -1)
            {
                startPos += 4;
                // startPos = buffer.IndexOf("title=\"", startPos);
                // startPos = buffer.IndexOf("\">", startPos) + 2;
                endPos = buffer.IndexOf("</h2>", startPos);
                title = buffer.Substring(startPos, endPos - startPos);
                title = Regex.Replace(title, "פרק.+הועלה", string.Empty);
            }
            m_searchRs.AddResult(title, seretHDLink, links, subsLink, "", ResultState.Verified);

            return;
        }

        private static void SetStatusMessageAndProgressAmount(RapidSearcher rapidSearcherForm, string message, int amount)
        {
            if (m_operationMode == OperationMode.GUI)
            {
                rapidSearcherForm.SetStatusMessgeAndProgressAmount(message, amount);
            }
        }

        private static void SearchLinksLoad(string searchString, string subsLink)
        {
            // Search
            string searchLink = "http://www.linksload.com/?s=" + searchString.Trim().Replace(" ", "+");

            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(searchLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                         SearchLinksLoadCB, new string[] { searchString, subsLink });
        }

        private static void SearchLinksLoadCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            if (buffer == null)
                return;

            if (buffer.Contains("Sorry, nothing found"))
            {
                return;
            }

            if (buffer.Length < 1)
            {
                return;
            }

            string[] strings = (string[])userState;
            string searchString = strings[0];
            string subsLink = strings[1];


            // Search result link
            string linksLoadLink;
            int startPos = 0;
            int endPos;
            while (true)
            {
                startPos = buffer.IndexOf("<h3><a href=\"http://www.linksload.com/", startPos + 1);
                if (startPos == -1)
                    break;
                endPos = buffer.IndexOf("rel=\"bookmark", startPos);

                if (m_searchRs.ShouldPickTheLink(buffer, startPos, endPos, searchString, m_searchOrder))
                {
                    linksLoadLink = buffer.Substring(startPos + 13, endPos - startPos - 15);
                    AsyncWebRequest request = new AsyncWebRequest();
                    request.SendWebBBRequest(linksLoadLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                 CollectLinksLoadLinksCB, new string[] { linksLoadLink, subsLink });
                }
            }
        }

        private static void CollectLinksLoadLinksCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            int startPos;
            int endPos;

            string[] strings = (string[]) userState;
            string linksLoadLink = strings[0];
            string subsLink = strings[1];
            
            // Submit links
            startPos = buffer.IndexOf("http://www.filesonic.com/");
            endPos = buffer.IndexOf("<em>", startPos);
            if (endPos == -1)
                endPos = buffer.IndexOf("</div>", startPos);
            string linksBuffer = buffer.Substring(startPos, endPos - startPos);

            string[] rsLinks = linksBuffer.Split(new[] { "http://www.filesonic.com/" },
                                                 StringSplitOptions.RemoveEmptyEntries);

/*            for (int i = 0; i < rsLinks.Length; i++)
            {
                rsLinks[i] = rsLinks[i].Substring(0, rsLinks[i].IndexOf("\" target=\"_blank\">"));
            }*/

            List<string> links = m_searchRs.CleanLinks(rsLinks);
            if (links == null || links.Count == 0)
                return;

            // title="Permanent Link to Dragon Naturally Speaking Preferred v10">Dragon Naturally Speaking Preferred v10</a>
            startPos = buffer.IndexOf("<h2>");
            startPos = buffer.IndexOf("title=\"", startPos);
            startPos = buffer.IndexOf("\">", startPos) + 2;
            endPos = buffer.IndexOf("</a>", startPos);
            string title = buffer.Substring(startPos, endPos - startPos);

            m_searchRs.AddResult(title, linksLoadLink, links, subsLink, "", ResultState.Verified);
        }

        private static void SearchGoLeech(string chosenCleaned, string subsLink)
        {
            string searchLink = "http://goleech.org/?s=" + chosenCleaned.Trim().Replace(" ", "+");

            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(searchLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                         SearchGoLeechCB, new string[] { chosenCleaned, subsLink });
        }

        private static void SearchGoLeechCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            if (buffer == null)
                return;

            if (buffer.Contains("Sorry, but you are looking for something that is not here"))
            {
                return;
            }

            string[] strings = (string[])userState;
            string chosenCleaned = strings[0];
            string subsLink = strings[1];

            string goleechLink;
            int startPos = 0;
            int endPos;

            while (true)
            {
                startPos = buffer.IndexOf("<h2><a href=\"http://goleech.org", startPos + 1);
                if (startPos == -1)
                    return;

                endPos = buffer.IndexOf("rel=\"bookmark", startPos);

                if (m_searchRs.ShouldPickTheLink(buffer, startPos, endPos, chosenCleaned, m_searchOrder))
                {
                    goleechLink = buffer.Substring(startPos + 13, endPos - startPos - 15);
                    AsyncWebRequest request = new AsyncWebRequest();
                    request.SendWebBBRequest(goleechLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                 CollectGoLeechResultsCB, new string[] { goleechLink, subsLink });
                    break;
                }
            }
        }

        private static void CollectGoLeechResultsCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            int startPos;
            int endPos;

            string[] strings = (string[])userState;
            string goleechLink = strings[0];
            string subsLink = strings[1];

            if (buffer == null)
                return;

            // Collect links
            startPos = buffer.IndexOf("<a href=\"http://www.filesonic.com/");
            if (startPos == -1)
                return;
            endPos = buffer.IndexOf("<p><strong>", startPos);
            if (endPos == -1)
                endPos = buffer.IndexOf("</div>", startPos);
            if (endPos == -1)
                endPos = buffer.IndexOf("\" title", startPos);
            string linksBuffer = buffer.Substring(startPos, endPos - startPos);

            string[] rsLinks = linksBuffer.Split(new[] { "<a href=\"http://www.filesonic.com/" },
                                                 StringSplitOptions.RemoveEmptyEntries);

            if (rsLinks.Length > 1)
            {
                for (int i = 0; i < rsLinks.Length; i++)
                {
                    rsLinks[i] = rsLinks[i].Substring(0, rsLinks[i].IndexOf("\" title=\"http://rapidshare"));
                }
            }

            List<string> links = m_searchRs.CleanLinks(rsLinks);
            if (links == null || links.Count == 0)
                return;

            // title="Permanent Link to Dragon Naturally Speaking Preferred v10">Dragon Naturally Speaking Preferred v10</a>
            startPos = buffer.IndexOf("<div class=\"post\"");
            startPos = buffer.IndexOf("<h2>", startPos);
            startPos = buffer.IndexOf("title=\"", startPos);
            startPos = buffer.IndexOf("\">", startPos) + 2;
            endPos = buffer.IndexOf("</a>", startPos);
            string title = buffer.Substring(startPos, endPos - startPos);

            m_searchRs.AddResult(title, goleechLink, links, subsLink, "", ResultState.Verified);
        }

        private static void SearchIRFree(string searchString, string subsLink)
        {
            string searchLink = "http://www.irfree.com/?s=" + searchString.Trim().Replace(" ", "+");

            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(searchLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                         SearchIRFreeCB, new string[] { searchString, subsLink });
        }

        private static void SearchIRFreeCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            if (buffer == null || buffer.Contains("Sorry, no posts matched your criteria"))
            {
                return;
            }

            string[] strings = (string[])userState;
            string searchString = strings[0];
            string subsLink = strings[1];

            string irfreeLink;
            int startPos = 0;
            int endPos;
            while (true)
            {
                startPos = buffer.IndexOf("storytitle\"><a href=\"http://www.irfree.com", startPos+1);
                if (startPos == -1)
                    break;
                endPos = buffer.IndexOf("rel=\"bookmark", startPos);

                if (m_searchRs.ShouldPickTheLink(buffer, startPos, endPos, searchString, m_searchOrder))
                {
                    irfreeLink = buffer.Substring(startPos + 21, endPos - startPos - 23);
                    AsyncWebRequest request = new AsyncWebRequest();
                    request.SendWebBBRequest(irfreeLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                 CollectIrFreeLinksCB, new string[] { irfreeLink, subsLink });
                }
            }
        }

        private static void CollectIrFreeLinksCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            int startPos;
            int endPos;

            string[] strings = (string[])userState;
            string irfreeLink = strings[0];
            string subsLink = strings[1];

            if (buffer == null)
                return;

            // Submit links
            startPos = buffer.IndexOf("http://www.filesonic.com/");
            if (startPos == -1)
                return;
            endPos = buffer.IndexOf("<p><strong>", startPos);
            if (endPos == -1)
                return;
            string resultBuffer = buffer.Substring(startPos, endPos - startPos);

            string[] rsLinks = resultBuffer.Split(new[] { "http://www.filesonic.com/" },
                                                  StringSplitOptions.RemoveEmptyEntries);

            List<string> links = m_searchRs.CleanLinks(rsLinks);
            if (links == null || links.Count == 0)
                return;

            startPos = buffer.IndexOf("<div class=\"post\"");
            startPos = buffer.IndexOf("rel=\"bookmark\">", startPos) + 15;
            endPos = buffer.IndexOf("</a>", startPos);
            string title = buffer.Substring(startPos, endPos - startPos);

            // Search for password and add it to password list
            string pwd = "";
            int passStartPos = buffer.IndexOf("pass:", endPos, StringComparison.OrdinalIgnoreCase);
            if (passStartPos > -1)
            {
                const string c_startCode = "<br />\n";
                startPos = buffer.IndexOf(c_startCode, passStartPos);
                endPos = buffer.IndexOf("<", startPos+c_startCode.Length+1);
                if ((endPos - startPos) < 100)
                {
                    pwd = buffer.Substring(startPos + c_startCode.Length, endPos - startPos - c_startCode.Length);
                    m_searchRs.AddPasswordToPasswordsFile(pwd);
                }
            }

            if (buffer != null)
            {
                Regex passwordPattern = new Regex("<b>Password : </b> (.+)\r\n");
                Match m = passwordPattern.Match(buffer);
                if (m.Success)
                {
                    pwd = m.Groups[1].Value;
                    m_searchRs.AddPasswordToPasswordsFile(pwd);
                }
            }

            m_searchRs.AddResult(title, irfreeLink, links, subsLink, pwd, ResultState.Verified);
        }

        public static void OnTitleClick(DataGridViewCell button)
        {
            int rowId = button.RowIndex;
            if (m_searchResults.GetResultState(rowId) != ResultState.Verified)
            {
                MessageBox.Show("Only verified (black) results are valid for clicking.");
                return;
            }

            string title = ((ResultDetails) button.Value).Title;
            string url = ((ResultDetails) button.Value).Url;
            List<string> rsLinks = m_searchResults.GetLinks(rowId);
            string subsLink = m_searchResults.GetSubsLink(rowId);

            m_searchRs.AddAllResultsToDm(rsLinks, subsLink, m_searchResults.GetPassword(rowId), title, url);
        }

        private static void SearchOneDDL(string searchString, string subsLink)
        {

            string searchLink = "http://www.oneddl.com/?s=" + searchString.Trim().Replace(" ", "+");

            AsyncWebRequest request = new AsyncWebRequest();
            request.SendWebBBRequest(searchLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                         SearchOneDDLCB, new string[] { searchString, subsLink });
        }

        private static void SearchOneDDLCB(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            if (buffer == null || buffer.Contains("but the page you're looking for isn't here"))
            {
                return;
            }

            string[] strings = (string[])userState;
            string searchString = strings[0];
            string subsLink = strings[1];

            string oneddlLink;
            int startPos = 0;
            int endPos;
            while (true)
            {
                startPos = buffer.IndexOf("div class=\"posttitle\"", startPos + 1);
                if (startPos == -1)
                    break;
                endPos = buffer.IndexOf("/h2>", startPos);

                string descAndLink = buffer.Substring(startPos, endPos-startPos+1);
                Regex re = new Regex("<a href=\"([^\"]+)\"");
                Match m = re.Match(descAndLink);
                if (m.Success)
                {
                    oneddlLink = m.Groups[1].Value;
                    AsyncWebRequest request = new AsyncWebRequest();
                    request.SendWebBBRequest(oneddlLink, "", "", 3, "", false, "", m_shouldStopEvent, 0, "", false,
                                CollectOneDDLLinks, new string[] { oneddlLink, subsLink, searchString });
                }
            }
        }

        private static void CollectOneDDLLinks(string buffer, HttpWebResponse respObj, string searchCookieParam, object userState)
        {
            string[] strings = (string[])userState;
            string oneddlLink = strings[0];
            string subsLink = strings[1];
            string searchString = strings[2];

            List<string> links = new List<string>();

            if (buffer == null)
                return;

//            <p><strong>Rapidshare</strong><br />
//            <a href="http://linksafe.me/d/5a46ce73e9/OneDDL.com-Mr.Sunshine.2011.S01E01.720p.HDTV.X264-DIMENSION.mkv">http://linksafe.me/d/5a46ce73e9/OneDDL.com-Mr.Sunshine.2011.S01E01.720p.HDTV.X264-DIMENSION.mkv</a></p>



            Regex []res = new Regex[2];
            res[0] = new Regex("\"(http://www.filesonic.com/[^\"]+)\"");
            res[1] = new Regex("<p><strong>Rapidshare</strong><br />[\n\t ]+<a href=\"(http://linksafe.me/d/[^\"]+)\"");

            for (int i = 0; i < 2; i++)
            {
                MatchCollection mc = res[i].Matches(buffer);
                foreach (Match m in mc)
                {
                    string link = m.Groups[1].Value;
                    if (m_searchRs.ShouldPickTheLink(link, 0, link.Length, searchString, m_searchOrder))
                    {
                        links.Add(link);
                    }
                    else
                    {
                        string filteredLink = Regex.Replace(link, "\\.[0-9]+\\.", " ");
                        string filteredSearchString = Regex.Replace(searchString, "S[0-9]+E[0-9]+", " ");
                        if (m_searchRs.ShouldPickTheLink(filteredLink, 0, filteredLink.Length, filteredSearchString, m_searchOrder))
                        {
                            links.Add(link);
                        }
                    }
                }
            }

            //<p><strong>Rapidshare</strong><br />
            // <a href="http://91526.oneddl.canhaz.it/">http://91526.oneddl.canhaz.it/</a></p>

            Regex re = new Regex("<p><strong>Rapidshare</strong><br />[\n\t ]+<a href=\"(http://[0-9]+.oneddl.canhaz.it/)\"");
            MatchCollection matches = re.Matches(buffer);
            foreach (Match match in matches)
            {
                WebRequest req = HttpWebRequest.Create(match.Groups[1].Value);
                WebResponse resp = req.GetResponse();
                StreamReader sr = new StreamReader(resp.GetResponseStream());
                string s = sr.ReadToEnd();
                Regex rsre = new Regex("\"(http://www.filesonic.com/[^\"]+)\"");
                Match rsmatch = rsre.Match(s);
                if (rsmatch.Success)
                {
                    links.Add(rsmatch.Groups[1].Value);
                }
            }


            if (m_searchOrder.Contains("720") || m_searchOrder.Contains("1080"))
            {
                for (int i = links.Count - 1; i >= 0; i--)
                {
                    if (!links[i].Contains("720") && !links[i].Contains("1080"))
                    {
                        links.RemoveAt(i);
                    }
                }
            }

            if (links.Count > 0)
            {
                string title = links[0].Replace(".part1.rar", "");
                int pos = title.LastIndexOf("/");
                if (pos > 0)
                    title = title.Substring(pos + 1);
                m_searchRs.AddResult(title, oneddlLink, links, subsLink, "", ResultState.Verified);
            }
        }

    }

    internal class NullNotifier : SearchRS.INotifications
    {
        public void SetStatusMessageAndProgressAmount(string message, int progressAmount)
        {
            
        }
    }
    internal class GuiNotifier : SearchRS.INotifications
    {
        private RapidSearcher m_form;

        public GuiNotifier(RapidSearcher form)
        {
            m_form = form;
        }

        public void SetStatusMessageAndProgressAmount(string message, int progressAmount)
        {
            if (progressAmount < 100)
                progressAmount = 0;
            m_form.SetStatusMessgeAndProgressAmount(message, progressAmount);
        }
    }

    internal class ConsoleNotifier : SearchRS.INotifications
    {
        public void SetStatusMessageAndProgressAmount(string message, int progressAmount)
        {
            Console.Write(progressAmount + ": " + message, progressAmount);
        }
    }



}